home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / lprd-src / lprd-print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-25  |  8.7 KB  |  432 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. #include <MacHeaders>
  12. #include <Printing.h>
  13. #include <Packages.h>
  14.  
  15. #define PostScriptBegin        190
  16. #define PostScriptEnd        191
  17. #define PostScriptHandle    192
  18.  
  19. #define LEFTSPACE        2
  20. #define TOPSPACE        2
  21. #define TABWIDTH        8
  22. #define EXTRAHEADROOM    10
  23.  
  24. #define EOF (-1)
  25.  
  26. extern char border_rect,print_format;
  27.  
  28. static short refnum;
  29. static FSSpec spec;
  30. static char have_spec;
  31. static TPrStatus myStRec;
  32. static int pagenum;
  33. static char notify_operation;
  34. static char pushback;
  35.  
  36. static int
  37. ungetc(char c)
  38. {
  39.     pushback = c;
  40. }
  41.  
  42. static int
  43. getc(void)
  44. {
  45.     long n;
  46.     short err;
  47.     unsigned char c;
  48.  
  49.     if (pushback != -1) {
  50.         c = pushback;
  51.         pushback = -1;
  52.         return c;
  53.     }
  54.     
  55.     n = 1;
  56.     err = FSRead(refnum,&n,&c);
  57.     if (err) return EOF;
  58.     return (int)c;
  59. }
  60.  
  61. static void
  62. idle_action(void)
  63. {
  64.     EvQElPtr q;
  65.  
  66.     if (PrError() == noErr) 
  67.         for (q = (EvQElPtr)GetEvQHdr()->qHead; q != 0L; q = (EvQElPtr)q->qLink)
  68.             if (q->evtQWhat == keyDown && (q->evtQModifiers & cmdKey) &&
  69.                     (char)q->evtQMessage == '.')
  70.                 PrSetError(iPrAbort);
  71.     
  72.     notify_message(notify_operation,notify_operation ? myStRec.iCurPage : pagenum,
  73.         myStRec.iTotPages,spec.name);
  74. }
  75.  
  76. static unsigned char *linebuf;
  77. static int linebuflen;
  78. static Point run_start;
  79. static int current_row,current_col,headspace,lineHeight;
  80. static FontInfo fi;
  81.  
  82. static void
  83. flush_run(void)
  84. {
  85.     Point pt;
  86.  
  87.     pt.h = LEFTSPACE + run_start.h * fi.widMax;
  88.     pt.v = TOPSPACE + headspace + lineHeight * run_start.v + fi.ascent;
  89.     MoveTo(pt.h,pt.v);
  90.     DrawText(linebuf,0,linebuflen);
  91. }
  92.  
  93. static void
  94. new_run(void)
  95. {
  96.     linebuflen = 0;
  97.     run_start.h = current_col;
  98.     run_start.v = current_row;
  99. }
  100.  
  101. static int
  102. get_job(char *driver_open,THPrint *hPrint)
  103. {
  104.     int err,invalid,accepted;
  105.     
  106.  retry:
  107.  
  108.     PrOpen();
  109.     if (PrError()) goto bail;
  110.     *driver_open = 1;
  111.  
  112.     err = get_preference('PREC',128,hPrint);
  113.     if (err) {
  114.         // Never printed before.  Must do page setup.
  115.         PrClose(); *driver_open = 0;
  116.         if (Alert(128,0L) == 1) {
  117.             err = do_page_setup();
  118.             if (err) goto bail;
  119.             if (Alert(133,0L) != 1) goto bail;
  120.             goto retry;
  121.         }
  122.     }
  123.  
  124.     invalid = PrValidate(*hPrint);
  125.     if (PrError()) goto bail;
  126.     if (invalid) {
  127.         // Not the same printer as last time.  Must do page setup
  128.         PrClose(); *driver_open = 0;
  129.         if (Alert(129,0L) == 1) {
  130.             err = do_page_setup();
  131.             if (err) goto bail;
  132.             if (Alert(133,0L) != 1) goto bail;
  133.             goto retry;
  134.         }
  135.     }
  136.  
  137.     accepted = PrJobDialog(*hPrint);
  138.     if (PrError() || !accepted) goto bail;
  139.     
  140.     return 0;
  141.     
  142.     bail:
  143.     return 1;
  144. }
  145.  
  146. static void
  147. print_text_file(void)
  148. {
  149.     int c;
  150.     THPrint hPrint;
  151.     TPPrPort myPrPort;
  152.     unsigned long dateTime;
  153.     short err;
  154.     unsigned char date[256],time[256],u[256],v[20];
  155.     char doc_open,page_complete,doc_complete,notify_open,driver_open,page_open;
  156.     int lines_per_page,cols_per_page;
  157.  
  158.     linebuf = 0L;
  159.     hPrint = 0L;
  160.     doc_open = 0;
  161.     page_open = 0;
  162.     notify_open = 0;
  163.     driver_open = 0;
  164.     pushback = -1;
  165.  
  166.     if (get_job(&driver_open,&hPrint)) goto bail;
  167.  
  168.     // Tech Note M.IM.pIdleProc says put this next statement here.
  169.     (**hPrint).prJob.pIdleProc = NewPrIdleProc(idle_action);
  170.  
  171.     myPrPort = PrOpenDoc(hPrint,0L,0L);
  172.     if (PrError()) goto bail;
  173.     doc_open = 1;
  174.     
  175.     GetDateTime(&dateTime);
  176.     IUDateString(dateTime,abbrevDate,date);
  177.     IUTimeString(dateTime,0,time);
  178.     pagenum = 1;
  179.  
  180.     notify_start();
  181.     notify_open = 1;
  182.     notify_operation = 0;
  183.  
  184.     doc_complete = 0;
  185.     while (!doc_complete) {
  186.         // Each pass through this loop is a page.
  187.         notify_message(0,pagenum,0,spec.name);
  188.         
  189.         PrOpenPage(myPrPort,0L);
  190.         if (PrError()) goto bail;
  191.         page_open = 1;
  192.  
  193.         SetPort((GrafPtr)myPrPort);
  194.         TextFont(monaco);
  195.         TextSize(9);
  196.  
  197.         if (border_rect) FrameRect(&myPrPort->gPort.portRect);
  198.  
  199.         if (linebuf == 0L) {
  200.             GetFontInfo(&fi);
  201.             lineHeight = fi.ascent + fi.descent + fi.leading;
  202.             headspace = (print_format ? lineHeight + EXTRAHEADROOM : 0);
  203.             lines_per_page = (myPrPort->gPort.portRect.bottom -
  204.                               myPrPort->gPort.portRect.top - 2*TOPSPACE -
  205.                               headspace + fi.leading) / lineHeight;
  206.             cols_per_page = (myPrPort->gPort.portRect.right -
  207.                 myPrPort->gPort.portRect.left - 2*LEFTSPACE) / fi.widMax;
  208.  
  209.             if (linebuf == 0L) {
  210.                 linebuf = (unsigned char *)NewPtr(cols_per_page+1);
  211.                 if (MemError()) goto bail;
  212.             }
  213.         }
  214.  
  215.         if (print_format) {
  216.             // Write name, date, and page number
  217.     
  218.             MoveTo(LEFTSPACE,TOPSPACE + lineHeight - fi.leading - fi.descent);
  219.             TextFace(bold);
  220.     
  221.             if (have_spec) {
  222.                 DrawString(spec.name);
  223.                 Move(20,0);
  224.             }
  225.     
  226.             DrawString(date);
  227.             Move(20,0);
  228.             DrawString(time);
  229.     
  230.             GetIndString(u,128,6);
  231.             NumToString(pagenum,v); pstrcat(u,v);
  232.             MoveTo(myPrPort->gPort.portRect.right - LEFTSPACE - StringWidth(u),
  233.                    myPrPort->gPort.pnLoc.v);
  234.             DrawString(u);
  235.  
  236.             TextFace(normal);
  237.         }
  238.  
  239.         current_row = 0;
  240.         current_col = 0;
  241.         new_run();
  242.  
  243.         // Keep reading and printing characters until we walk off the bottom of
  244.         // the page.
  245.         page_complete = 0;
  246.         while (!page_complete) {
  247.             if ((TickCount() & 63) == 0) {
  248.                 idle_action();
  249.                 if (PrError()) goto bail;
  250.             }
  251.  
  252.             c = getc();
  253.             switch (c) {
  254.             case EOF:
  255.                 flush_run();
  256.                 page_complete = doc_complete = 1;
  257.                 break;
  258.             case '\t':
  259.                 flush_run();
  260.                 current_col += TABWIDTH - current_col % TABWIDTH;;
  261.                 if (current_col >= cols_per_page) {
  262.                     ++current_row;
  263.                     if (current_row == lines_per_page)
  264.                         page_complete = 1;
  265.                     else {
  266.                         current_col = 0;
  267.                         new_run();
  268.                     }
  269.                 }
  270.                 else
  271.                     new_run();
  272.                 break;
  273.             case 'L' & 0x1f:
  274.                 flush_run();
  275.                 page_complete = 1;
  276.                 break;
  277.             case '\n':
  278.             case '\r':
  279.                 flush_run();
  280.                 ++current_row;
  281.                 if (current_row == lines_per_page)
  282.                     page_complete = 1;
  283.                 else {
  284.                     current_col = 0;
  285.                     new_run();
  286.                 }
  287.                 break;
  288.             default:
  289.                 if (current_col == cols_per_page) {
  290.                     ungetc(c);
  291.                     flush_run();
  292.                     ++current_row;
  293.                     if (current_row == lines_per_page)
  294.                         page_complete = 1;
  295.                     else {
  296.                         current_col = 0;
  297.                         new_run();
  298.                     }
  299.                 }
  300.                 else {
  301.                     linebuf[linebuflen] = c;
  302.                     ++linebuflen;
  303.                     ++current_col;
  304.                 }
  305.                 break;
  306.             }
  307.         }
  308.  
  309.         PrClosePage(myPrPort); page_open = 0;
  310.         if (PrError()) goto bail;
  311.         ++pagenum;
  312.     }
  313.  
  314.     PrCloseDoc(myPrPort); doc_open = 0;
  315.     if (PrError()) goto bail;
  316.     
  317.     notify_operation = 1;
  318.     if ((**hPrint).prJob.bJDocLoop == bSpoolLoop) {
  319.         notify_message(1,0,0,spec.name);
  320.         PrPicFile(hPrint,0L,0L,0L,&myStRec);
  321.     }
  322.  
  323.     bail:
  324.     if (page_open) PrClosePage(myPrPort);
  325.     if (doc_open) PrCloseDoc(myPrPort);
  326.     if (notify_open) notify_end();
  327.     if (linebuf) DisposPtr((Ptr)linebuf);
  328.     if (hPrint) DisposHandle((Handle)hPrint);
  329.     if (driver_open) PrClose();
  330. }
  331.  
  332. static void
  333. print_postscript_file(void)
  334. {
  335.     /* What follows is not the right way to send postscript directly to
  336.        a printer, but only a kludge.  One day we'll make it right. */
  337.  
  338. #define bufmax 4096
  339.     long n;
  340.     Handle buffer;
  341.     THPrint hPrint;
  342.     TPPrPort myPrPort;
  343.     short err;
  344.     char doc_open,doc_complete,notify_open,driver_open,page_open;
  345.  
  346.     hPrint = 0L;
  347.     buffer = 0L;
  348.     doc_open = 0;
  349.     page_open = 0;
  350.     notify_open = 0;
  351.     driver_open = 0;
  352.     
  353.     buffer = NewHandle(bufmax);
  354.     if (buffer == 0L) goto bail;
  355.  
  356.     if (get_job(&driver_open,&hPrint)) goto bail;
  357.  
  358.     // Tech Note M.IM.pIdleProc says put this next statement here.
  359.     (**hPrint).prJob.pIdleProc = NewPrIdleProc(idle_action);
  360.  
  361.     myPrPort = PrOpenDoc(hPrint,0L,0L);
  362.     if (PrError()) goto bail;
  363.     doc_open = 1;
  364.  
  365.     notify_start();
  366.     notify_open = 1;
  367.     notify_operation = 1;
  368.     notify_message(notify_operation,0,0,spec.name);
  369.  
  370.     PrOpenPage(myPrPort,0L);
  371.     if (PrError()) goto bail;
  372.     page_open = 1;
  373.  
  374.     SetPort((GrafPtr)myPrPort);
  375.     MoveTo(-32000,-32000);
  376.     Line(0,0);
  377.  
  378.     PicComment(PostScriptBegin,0,0L);
  379.     while (1) {
  380.         n = bufmax;
  381.         HLock(buffer);
  382.         err = FSRead(refnum,&n,*buffer);
  383.         HUnlock(buffer);
  384.         if (n == 0) break;
  385.         if (err && err != eofErr) break;
  386.         PicComment(PostScriptHandle,n,buffer);
  387.     }
  388.     PicComment(PostScriptEnd,0,0L);
  389.  
  390.     PrClosePage(myPrPort); page_open = 0;
  391.     if (PrError()) goto bail;
  392.  
  393.     PrCloseDoc(myPrPort); doc_open = 0;
  394.     if (PrError()) goto bail;
  395.     
  396.     if ((**hPrint).prJob.bJDocLoop == bSpoolLoop) {
  397.         notify_message(notify_operation,0,0,spec.name);
  398.         PrPicFile(hPrint,0L,0L,0L,&myStRec);
  399.     }
  400.  
  401.     bail:
  402.     if (page_open) PrClosePage(myPrPort);
  403.     if (doc_open) PrCloseDoc(myPrPort);
  404.     if (notify_open) notify_end();
  405.     if (buffer) DisposHandle(buffer);
  406.     if (hPrint) DisposHandle((Handle)hPrint);
  407.     if (driver_open) PrClose();
  408. }
  409.  
  410. void
  411. do_print_spec(FSSpec *spec0)
  412. {
  413.     short err;
  414.     char s[2];
  415.     long n;
  416.  
  417.     have_spec = 1;
  418.     spec = *spec0;
  419.  
  420.     err = FSpOpenDF(&spec,fsRdPerm,&refnum);
  421.     if (err) return;
  422.     n = 2;
  423.     err = FSRead(refnum,&n,s);
  424.     if (err && err != eofErr) { FSClose(refnum); return; }
  425.     SetFPos(refnum,fsFromStart,0);
  426.     if (n == 2 && s[0] == '%' && s[1] == '!')
  427.         print_postscript_file();
  428.     else
  429.         print_text_file();
  430.     FSClose(refnum);
  431. }
  432.